package view;
import events.ResizeEvent;
import flash.display.DisplayObject;
import flash.display.Sprite;
import flash.events.Event;
import flash.events.FocusEvent;
import flash.events.KeyboardEvent;
import flash.events.MouseEvent;
import flash.Lib;
import flash.text.TextField;
import flash.text.TextFieldType;
import graphic.RenderObject;
import gui.buttons.CheckBox;
import gui.buttons.SimpleButton;
import view.events.LevelEditorViewOtherEvent;

enum E_PropertyType
{
	INSTANCE_NAME;
	X_POSITION;
	Y_POSITION;
	X_SCALE;
	Y_SCALE;
	ROTATION;
	STATIC;
}

/**
 * @author Damien Mabin
 */

class PropertyPanel extends Sprite
{
	private var m_Style 			: { backgroundColor : UInt, separatorColor : UInt, buttonBackgroundColor : UInt, buttonForegroundColor : UInt };
	private var m_ButtonStyle		: { backgroundColor : UInt, backgroundAlpha : Float, borderColor : UInt, borderAlpha : Float, borderSize : Int, foregroundColor : UInt };
	private var m_CheckBoxStyle		: { backgroundColor : UInt, backgroundAlpha : Float, borderColor : UInt, borderAlpha : Float, borderSize : Int };
	private var m_AllInfos			: Array<{ label : TextField, value : DisplayObject }>;
	private var m_DisplayedInfos	: Array<{ label : TextField, value : DisplayObject }>;
	private var m_Title 			: TextField;
	
	// All the property available, maybe some can't be shown, depend of the context/mode of edition
	private var m_EltType 			: { label : TextField, value : DisplayObject };
	private var m_EltModelName		: { label : TextField, value : DisplayObject };
	private var m_EltInstanceName	: { label : TextField, value : DisplayObject };
	private var m_PosX				: { label : TextField, value : DisplayObject };
	private var m_PosY				: { label : TextField, value : DisplayObject };
	private var m_ScaleX			: { label : TextField, value : DisplayObject };
	private var m_ScaleY			: { label : TextField, value : DisplayObject };
	private var m_Rotation			: { label : TextField, value : DisplayObject };
	private var m_PhysicalShape		: { label : TextField, value : DisplayObject };
	private var m_Static			: { label : TextField, value : DisplayObject };
	
	// The element for wich we are displaying informations
	private var m_CurrentElement	: Dynamic;
	
	public function new(?_Style:{ backgroundColor : UInt, separatorColor : UInt, buttonBackgroundColor : UInt, buttonForegroundColor : UInt }) 
	{
		super();
		if (_Style != null)
		{
			m_Style = _Style;
		}
		else
		{
			m_Style = { backgroundColor : 0x000000, separatorColor : 0xFF0000, buttonBackgroundColor : 0xFFFF00, buttonForegroundColor : 0x00FFFF };
		}
		m_ButtonStyle = { backgroundColor : m_Style.buttonBackgroundColor, backgroundAlpha : 1.0, borderColor : 0x000000, borderAlpha : 1.0, borderSize : 0, foregroundColor : m_Style.buttonForegroundColor };
		m_CheckBoxStyle = { backgroundColor : m_Style.buttonBackgroundColor, backgroundAlpha : 1.0, borderColor : 0x000000, borderAlpha : 1.0, borderSize : 0 };
		m_AllInfos = new Array<{ label : TextField, value : DisplayObject }>();
		m_DisplayedInfos = new Array<{ label : TextField, value : DisplayObject }>();
		this.focusRect = false;
		
		// ==========================================================================================================
		// Title :
		m_Title = new TextField();
		m_Title.text = "Properties :";
		m_Title.mouseEnabled = false;
		m_Title.selectable = false;
		m_Title.height = 20;
		
		// ==========================================================================================================
		// Infos :
		m_EltType 			= { label : new TextField(), value : cast new TextField() };
		cast(m_EltType.value, TextField).mouseEnabled = false;
		m_AllInfos.push(m_EltType);
		
		m_EltInstanceName	= { label : new TextField(), value : cast new TextField() };
		cast(m_EltInstanceName.value, TextField).mouseEnabled = false;
		cast(m_EltInstanceName.value, TextField).addEventListener(FocusEvent.FOCUS_OUT, callback(OnLooseFocusEvent, E_PropertyType.INSTANCE_NAME));
		cast(m_EltInstanceName.value, TextField).addEventListener(KeyboardEvent.KEY_DOWN, callback(OnKeyboardTextInputEvent, E_PropertyType.INSTANCE_NAME));
		m_AllInfos.push(m_EltInstanceName);
		
		m_EltModelName		= { label : new TextField(), value : cast new TextField() };
		cast(m_EltModelName.value, TextField).mouseEnabled = false;
		m_AllInfos.push(m_EltModelName);
		
		m_PosX				= { label : new TextField(), value : cast new TextField() };
		cast(m_PosX.value, TextField).mouseEnabled = false;
		cast(m_PosX.value, TextField).addEventListener(FocusEvent.FOCUS_OUT, callback(OnLooseFocusEvent, E_PropertyType.X_POSITION));
		cast(m_PosX.value, TextField).addEventListener(KeyboardEvent.KEY_DOWN, callback(OnKeyboardTextInputEvent, E_PropertyType.X_POSITION));
		m_AllInfos.push(m_PosX);
		
		m_PosY				= { label : new TextField(), value : cast new TextField() };
		cast(m_PosY.value, TextField).mouseEnabled = false;
		cast(m_PosY.value, TextField).addEventListener(FocusEvent.FOCUS_OUT, callback(OnLooseFocusEvent, E_PropertyType.Y_POSITION));
		cast(m_PosY.value, TextField).addEventListener(KeyboardEvent.KEY_DOWN, callback(OnKeyboardTextInputEvent, E_PropertyType.Y_POSITION));
		m_AllInfos.push(m_PosY);
		
		m_ScaleX			= { label : new TextField(), value : cast new TextField() };
		cast(m_ScaleX.value, TextField).mouseEnabled = false;
		cast(m_ScaleX.value, TextField).addEventListener(FocusEvent.FOCUS_OUT, callback(OnLooseFocusEvent, E_PropertyType.X_SCALE));
		cast(m_ScaleX.value, TextField).addEventListener(KeyboardEvent.KEY_DOWN, callback(OnKeyboardTextInputEvent, E_PropertyType.X_SCALE));
		m_AllInfos.push(m_ScaleX);
		
		m_ScaleY			= { label : new TextField(), value : cast new TextField() };
		cast(m_ScaleY.value, TextField).mouseEnabled = false;
		cast(m_ScaleY.value, TextField).addEventListener(FocusEvent.FOCUS_OUT, callback(OnLooseFocusEvent, E_PropertyType.Y_SCALE));
		cast(m_ScaleY.value, TextField).addEventListener(KeyboardEvent.KEY_DOWN, callback(OnKeyboardTextInputEvent, E_PropertyType.Y_SCALE));
		m_AllInfos.push(m_ScaleY);
		
		m_Rotation			= { label : new TextField(), value : cast new TextField() };
		cast(m_Rotation.value, TextField).mouseEnabled = false;
		cast(m_Rotation.value, TextField).addEventListener(FocusEvent.FOCUS_OUT, callback(OnLooseFocusEvent, E_PropertyType.ROTATION));
		cast(m_Rotation.value, TextField).addEventListener(KeyboardEvent.KEY_DOWN, callback(OnKeyboardTextInputEvent, E_PropertyType.ROTATION));
		m_AllInfos.push(m_Rotation);
		
		m_PhysicalShape		= { label : new TextField(), value : cast new SimpleButton("Edit", null, m_ButtonStyle) };
		m_PhysicalShape.value.dispatchEvent(new ResizeEvent(35, 18));
		m_PhysicalShape.value.addEventListener(MouseEvent.MOUSE_DOWN, OnMouseEvent);
		m_PhysicalShape.value.visible = false;
		m_AllInfos.push(m_PhysicalShape);
		
		m_Static			= { label : new TextField(), value : cast new CheckBox(m_CheckBoxStyle) };
		m_Static.value.dispatchEvent(new ResizeEvent(16, 16));
		m_Static.value.addEventListener(MouseEvent.MOUSE_DOWN, OnMouseEvent);
		m_Static.value.visible = false;
		m_AllInfos.push(m_Static);
		
		// ==========================================================================================================
		for (info in m_AllInfos)
		{
			this.addChild(info.label);
			info.label.mouseEnabled = false;
			info.label.selectable = false;
			this.addChild(info.value);
		}
		this.addChild(m_Title);
		
		this.addEventListener(ResizeEvent.EVENT, OnResizeEvent);
	}
	
	private function OnKeyboardTextInputEvent(_Type:E_PropertyType, _Evt:KeyboardEvent):Void
	{
		switch(_Type)
		{
			case INSTANCE_NAME :
			{
				if (_Evt.keyCode == 13 /*Enter*/)
				{
					Lib.current.stage.focus = this;
				}
			}
			case X_POSITION :
			{
				if (_Evt.keyCode == 13 /*Enter*/)
				{
					Lib.current.stage.focus = this;
				}
			}
			case Y_POSITION :
			{
				if (_Evt.keyCode == 13 /*Enter*/)
				{
					Lib.current.stage.focus = this;
				}
			}
			case X_SCALE :
			{
				if (_Evt.keyCode == 13 /*Enter*/)
				{
					Lib.current.stage.focus = this;
				}
			}
			case Y_SCALE :
			{
				if (_Evt.keyCode == 13 /*Enter*/)
				{
					Lib.current.stage.focus = this;
				}
			}
			case ROTATION :
			{
				if (_Evt.keyCode == 13 /*Enter*/)
				{
					Lib.current.stage.focus = this;
				}
			}
			case STATIC :
			{
			}
		}
	}
	
	private function OnMouseEvent(_Evt:MouseEvent):Void
	{
		if (_Evt.currentTarget == m_PhysicalShape.value)
		{
			this.dispatchEvent(new LevelEditorViewOtherEvent(E_OtherInteractionType.EDIT_RENDER_OBJECT_PHYSIC_BODY(cast m_CurrentElement)));
		}
		else if(_Evt.currentTarget == m_Static.value)
		{
			this.dispatchEvent(new LevelEditorViewOtherEvent(E_OtherInteractionType.CHANGE_RENDER_OBJECT_PROPERTY(cast m_CurrentElement, STATIC, ""+!cast(m_Static.value, CheckBox).GetState())));
		}
	}
	
	private function OnLooseFocusEvent(_Type:E_PropertyType, _Evt:Event):Void
	{
		switch(_Type)
		{
			case INSTANCE_NAME :
			{
				this.dispatchEvent(new LevelEditorViewOtherEvent(E_OtherInteractionType.CHANGE_RENDER_OBJECT_PROPERTY(cast m_CurrentElement, INSTANCE_NAME, cast(m_EltInstanceName.value, TextField).text)));
			}
			case X_POSITION :
			{
				this.dispatchEvent(new LevelEditorViewOtherEvent(E_OtherInteractionType.CHANGE_RENDER_OBJECT_PROPERTY(cast m_CurrentElement, X_POSITION, cast(m_PosX.value, TextField).text)));
			}
			case Y_POSITION :
			{
				this.dispatchEvent(new LevelEditorViewOtherEvent(E_OtherInteractionType.CHANGE_RENDER_OBJECT_PROPERTY(cast m_CurrentElement, Y_POSITION, cast(m_PosY.value, TextField).text)));
			}
			case X_SCALE :
			{
				this.dispatchEvent(new LevelEditorViewOtherEvent(E_OtherInteractionType.CHANGE_RENDER_OBJECT_PROPERTY(cast m_CurrentElement, X_SCALE, cast(m_ScaleX.value, TextField).text)));
			}
			case Y_SCALE :
			{
				this.dispatchEvent(new LevelEditorViewOtherEvent(E_OtherInteractionType.CHANGE_RENDER_OBJECT_PROPERTY(cast m_CurrentElement, Y_SCALE, cast(m_ScaleY.value, TextField).text)));
			}
			case ROTATION :
			{
				this.dispatchEvent(new LevelEditorViewOtherEvent(E_OtherInteractionType.CHANGE_RENDER_OBJECT_PROPERTY(cast m_CurrentElement, ROTATION, cast(m_Rotation.value, TextField).text)));
			}
			case STATIC :
			{
				this.dispatchEvent(new LevelEditorViewOtherEvent(E_OtherInteractionType.CHANGE_RENDER_OBJECT_PROPERTY(cast m_CurrentElement, STATIC, ""+cast(m_Static.value, CheckBox).GetState())));
			}
		}
	}
	
	public function DisplayPropertiesForPhysics<T>(_Class:Class<T>, _Elt:T):Void
	{
		m_CurrentElement = _Elt;
		for (info in m_DisplayedInfos)
		{
			info.value.visible = false;
			info.label.visible = false;
		}
		
		m_DisplayedInfos = new Array<{ label : TextField, value : DisplayObject }>();
		
		if (_Elt != null)
		{
			switch(_Class)
			{
				case cast RenderObject :
				{
					var ro : RenderObject = cast _Elt;
					
					m_EltModelName.label.text = "Model name";
					cast(m_EltModelName.value, TextField).text = ro.GetModelName();
					cast(m_EltModelName.value, TextField).height = 20;
					m_DisplayedInfos.push(m_EltModelName);
					
					m_EltInstanceName.label.text = "Instance name";
					cast(m_EltInstanceName.value, TextField).text = ro.name;
					cast(m_EltInstanceName.value, TextField).mouseEnabled = true;
					cast(m_EltInstanceName.value, TextField).selectable = true;
					cast(m_EltInstanceName.value, TextField).height = 20;
					cast(m_EltInstanceName.value, TextField).type = TextFieldType.INPUT;
					m_DisplayedInfos.push(m_EltInstanceName);
					
					m_PosX.label.text = "X";
					cast(m_PosX.value, TextField).text = "" + ro.GetPosition().x;
					cast(m_PosX.value, TextField).mouseEnabled = true;
					cast(m_PosX.value, TextField).selectable = true;
					cast(m_PosX.value, TextField).height = 20;
					cast(m_PosX.value, TextField).type = TextFieldType.INPUT;
					m_DisplayedInfos.push(m_PosX);
					
					m_PosY.label.text = "Y";
					cast(m_PosY.value, TextField).text = "" + ro.GetPosition().y;
					cast(m_PosY.value, TextField).mouseEnabled = true;
					cast(m_PosY.value, TextField).selectable = true;
					cast(m_PosY.value, TextField).height = 20;
					cast(m_PosY.value, TextField).type = TextFieldType.INPUT;
					m_DisplayedInfos.push(m_PosY);
					
					m_Rotation.label.text = "Rotation";
					cast(m_Rotation.value, TextField).text = "" + ro.GetPhysicalBody().a*180/Math.PI;
					cast(m_Rotation.value, TextField).mouseEnabled = true;
					cast(m_Rotation.value, TextField).selectable = true;
					cast(m_Rotation.value, TextField).height = 20;
					cast(m_Rotation.value, TextField).type = TextFieldType.INPUT;
					m_DisplayedInfos.push(m_Rotation);
					
					m_Static.label.text = "Static";
					cast(m_Static.value, CheckBox).SetState(ro.GetPhysicalBody().isStatic);
					m_DisplayedInfos.push(m_Static);
					
					m_PhysicalShape.label.text = "Physic body";
					m_DisplayedInfos.push(m_PhysicalShape);
				}
				default :
				{
					
				}
			}
		}
		
		OnResizeEvent(new ResizeEvent(this.width, this.height));
	}
	
	public function DisplayProperties<T>(_Class:Class<T>, _Elt:T):Void
	{
		m_CurrentElement = _Elt;
		for (info in m_DisplayedInfos)
		{
			info.value.visible = false;
			info.label.visible = false;
		}
		
		m_DisplayedInfos = new Array<{ label : TextField, value : DisplayObject }>();
		
		if (_Elt != null)
		{
			switch(_Class)
			{
				case cast RenderObject :
				{
					var ro : RenderObject = cast _Elt;
					
					m_EltType.label.text = "Type";
					cast(m_EltType.value, TextField).text = "RenderObject";
					cast(m_EltType.value, TextField).height = 20;
					m_DisplayedInfos.push(m_EltType);
					
					m_EltModelName.label.text = "Model name";
					cast(m_EltModelName.value, TextField).text = ro.GetModelName();
					cast(m_EltModelName.value, TextField).height = 20;
					m_DisplayedInfos.push(m_EltModelName);
					
					m_EltInstanceName.label.text = "Instance name";
					cast(m_EltInstanceName.value, TextField).text = ro.name;
					cast(m_EltInstanceName.value, TextField).mouseEnabled = true;
					cast(m_EltInstanceName.value, TextField).selectable = true;
					cast(m_EltInstanceName.value, TextField).height = 20;
					cast(m_EltInstanceName.value, TextField).type = TextFieldType.INPUT;
					m_DisplayedInfos.push(m_EltInstanceName);
					
					m_PosX.label.text = "X";
					cast(m_PosX.value, TextField).text = "" + (Math.floor(ro.GetPosition().x*100)/100);
					cast(m_PosX.value, TextField).mouseEnabled = true;
					cast(m_PosX.value, TextField).selectable = true;
					cast(m_PosX.value, TextField).height = 20;
					cast(m_PosX.value, TextField).type = TextFieldType.INPUT;
					m_DisplayedInfos.push(m_PosX);
					
					m_PosY.label.text = "Y";
					cast(m_PosY.value, TextField).text = "" + (Math.floor(ro.GetPosition().y*100)/100);
					cast(m_PosY.value, TextField).mouseEnabled = true;
					cast(m_PosY.value, TextField).selectable = true;
					cast(m_PosY.value, TextField).height = 20;
					cast(m_PosY.value, TextField).type = TextFieldType.INPUT;
					m_DisplayedInfos.push(m_PosY);
					
					m_Rotation.label.text = "Rotation";
					cast(m_Rotation.value, TextField).text = "" + ro.rotation;
					cast(m_Rotation.value, TextField).mouseEnabled = true;
					cast(m_Rotation.value, TextField).selectable = true;
					cast(m_Rotation.value, TextField).height = 20;
					cast(m_Rotation.value, TextField).type = TextFieldType.INPUT;
					m_DisplayedInfos.push(m_Rotation);
					
					m_ScaleX.label.text = "Scale X";
					cast(m_ScaleX.value, TextField).text = "" + ro.scaleX;
					cast(m_ScaleX.value, TextField).mouseEnabled = true;
					cast(m_ScaleX.value, TextField).selectable = true;
					cast(m_ScaleX.value, TextField).height = 20;
					cast(m_ScaleX.value, TextField).type = TextFieldType.INPUT;
					m_DisplayedInfos.push(m_ScaleX);
					
					m_ScaleY.label.text = "Scale Y";
					cast(m_ScaleY.value, TextField).text = "" + ro.scaleY;
					cast(m_ScaleY.value, TextField).mouseEnabled = true;
					cast(m_ScaleY.value, TextField).selectable = true;
					cast(m_ScaleY.value, TextField).height = 20;
					cast(m_ScaleY.value, TextField).type = TextFieldType.INPUT;
					m_DisplayedInfos.push(m_ScaleY);
					
					m_PhysicalShape.label.text = "Physic body";
					m_DisplayedInfos.push(m_PhysicalShape);
				}
				default :
				{
					
				}
			}
		}
		
		OnResizeEvent(new ResizeEvent(this.width, this.height));
	}
	
	private function OnResizeEvent(_Evt:ResizeEvent):Void
	{
		this.graphics.clear();
		this.graphics.beginFill(m_Style.backgroundColor);
		this.graphics.drawRect(0, 0, _Evt.m_Width, _Evt.m_Height);
		this.graphics.endFill();
		
		this.graphics.beginFill(m_Style.separatorColor);
		this.graphics.drawRect(_Evt.m_Width * 0.45-3, 24, 1, _Evt.m_Height-26);
		this.graphics.endFill();
		
		this.graphics.beginFill(m_Style.separatorColor);
		this.graphics.drawRect(5, 20, _Evt.m_Width-10, 2);
		this.graphics.endFill();
		
		var verticalOffset : Float = 22;
		
		for (info in m_DisplayedInfos)
		{
			info.label.visible = true;
			info.label.y = verticalOffset;
			info.label.x = _Evt.m_Width * 0.15;
			info.label.height = 20;
			
			info.value.visible = true;
			info.value.y = verticalOffset;
			info.value.x = _Evt.m_Width * 0.45;
			info.label.height = 20;
			
			verticalOffset += 20;
			
			this.graphics.beginFill(m_Style.separatorColor);
			this.graphics.drawRect(5, verticalOffset, _Evt.m_Width-10, 1);
			this.graphics.endFill();
		}
	}
	
}